﻿using System;
using JetBrains.Annotations;
using JetBrains.Application.Progress;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Bulbs;
using JetBrains.ReSharper.Feature.Services.CSharp.Bulbs;
using JetBrains.ReSharper.Intentions.Util;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.TextControl;
using JetBrains.Util;
using MugenMvvmToolkit.ReSharper.Infrastructure;

namespace MugenMvvmToolkit.ReSharper.ViewModels.ContextActions
{
    [ContextAction(Name = "IgnorePropertyAttributeAction", Group = "C#", Priority = 1)]
    public class IgnorePropertyAttributeAction : PropertyContextAction
    {
        #region Constructors

        public IgnorePropertyAttributeAction([NotNull] ICSharpContextActionDataProvider provider)
            : base(provider)
        {
        }

        #endregion

        #region Overrides of ContextActionBase

        /// <summary>
        ///     Popup menu item text
        /// </summary>
        public override string Text
        {
            get { return UiResources.AddIgnorePropertyAttribute; }
        }

        /// <summary>
        ///     Executes QuickFix or ContextAction. Returns post-execute method.
        /// </summary>
        /// <returns>
        ///     Action to execute after document and PSI transaction finish. Use to open TextControls, navigate caret, etc.
        /// </returns>
        protected override Action<ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
        {
            AddIgnorePropertyAttribute(Provider.ElementFactory, TypeProvider, PropertyDeclaration);
            return null;
        }

        /// <summary>
        ///     Check if this action is available at the constructed context.
        ///     Actions could store precalculated info in <paramref name="cache" /> to share it between different actions
        /// </summary>
        /// <returns>
        ///     true if this bulb action is available, false otherwise.
        /// </returns>
        protected override bool IsAvailableInternal(IUserDataHolder cache)
        {
            return TypeProvider.IgnorePropertyAttribute.IsResolved &&
                   !PropertyDeclaration.HasAttributeInstance(TypeProvider.IgnorePropertyAttribute) &&
                   ClassDeclaration.IsOfType(TypeProvider.ValidatableViewModel);
        }

        #endregion

        #region Methods

        public static void AddIgnorePropertyAttribute(CSharpElementFactory factory, TypeProvider typeProvider,
            IPropertyDeclaration property)
        {
            IAttribute attribute = factory.CreateAttribute(typeProvider.IgnorePropertyAttribute.GetTypeElement());
            attribute = property.AddAttributeAfter(attribute, null);
            ContextActionUtils.FormatWithDefaultProfile(attribute);
        }

        #endregion
    }
}